﻿using System;
using System.Linq;
using System.IO;
using System.Collections.Generic;
using System.Web;
using System.Web.Caching;

namespace Hxsoft.AppV1.Module
{
	/// <summary>
	/// 专题动态内容模板。
	/// </summary>
	[Serializable]
	public class SpecialContentTemplate
	{
		/// <summary>
		/// 用户定义的模板参数键。
		/// </summary>
		public const string CustomTemplateParameterKey = "CustomTemplate";

		/// <summary>
		/// 名称。
		/// </summary>
		public string Name { get; set; }

		/// <summary>
		/// 视图类型。
		/// </summary>
		public string ViewType { get; set; }

		/// <summary>
		/// 模板。
		/// </summary>
		public string Template { get; set; }

		/// <summary>
		/// 模板的其它参数。
		/// </summary>
		public Dictionary<string, SpecialTemplateParameter> OtherParameters { get; set; }

		/// <summary>
		/// 可选的风格。
		/// </summary>
		public Dictionary<string, string> Styles { get; set; }

		/// <summary>
		/// 默认图片路径。
		/// </summary>
		public string DefaultImageUrl { get; set; }

		/// <summary>
		/// 头部包含的文件。
		/// </summary>
		public Dictionary<string, IncludeFileType> HeadIncludeFiles { get; set; }



		/// <summary>
		/// 获取内容模板。
		/// </summary>
		/// <param name="inputParameters">输入的参数。</param>
		/// <returns>内容模板。</returns>
		public string GetTemplate(Dictionary<string, string> inputParameters)
		{
			if (inputParameters == null ||
				!inputParameters.ContainsKey(CustomTemplateParameterKey))
				return Template;
			return inputParameters[CustomTemplateParameterKey];
		}
	}

	/// <summary>
	/// 参数验证类型。
	/// </summary>
	public enum ParameterValidationType
	{
		/// <summary>
		/// 不进行验证。
		/// </summary>
		None,

		/// <summary>
		/// 正则表达式验证。
		/// </summary>
		Regex
	}

	/// <summary>
	/// 专题模板参数。
	/// </summary>
	public struct SpecialTemplateParameter
	{
		/// <summary>
		/// 参数名。
		/// </summary>
		public string Name { get; set; }

		/// <summary>
		/// 参数验证类型。
		/// </summary>
		public ParameterValidationType ValidationType { get; set; }

		/// <summary>
		/// 验证值。
		/// </summary>
		public string ValidationValue { get; set; }

		/// <summary>
		/// 描述。
		/// </summary>
		public string Description { get; set; }

		/// <summary>
		/// 输入格式化。
		/// </summary>
		public string OutputFormat { get; set; }

		/// <summary>
		/// 可选项。
		/// </summary>
		public Dictionary<string, string> Options { get; set; }

		/// <summary>
		/// 默认值。
		/// </summary>
		public string DefaultValue { get; set; }
	}

	/// <summary>
	/// 专题模板配置。
	/// </summary>
	[Serializable]
	public class SpecialTemplateConfiguration
	{
		/// <summary>
		/// 网站导航模板。
		/// </summary>
		public string WebsiteNavigationTemplate { get; set; }

		/// <summary>
		/// 专题主导航模板。
		/// </summary>
		public string MainNavigationTemplate { get; set; }

		/// <summary>
		/// 当前位置模板。
		/// </summary>
		public string CurrentLocationTemplate { get; set; }

		/// <summary>
		/// 版权信息模板。
		/// </summary>
		public string CopyrightInfoTemplate { get; set; }

		/// <summary>
		/// 模板样式Url。
		/// </summary>
		public string[] TemplateCssUrls { get; set; }

		/// <summary>
		/// 默认图片路径。
		/// </summary>
		public string DefaultImageUrl { get; set; }




		#region 变量
		/// <summary>
		/// 网站列表。
		/// </summary>
		public List<NavigationItem> Websites { get; set; }

		/// <summary>
		/// 区块预览数据。
		/// </summary>
		/// <remarks>
		/// 第一级字典键为模块类型。
		/// 第二级字典键为预览数据对应的模板类型。
		/// </remarks>
		public Dictionary<string, Dictionary<string, string>> BlockPreviewData { get; set; }

		/// <summary>
		/// 区块模板。
		/// </summary>
		/// <remarks>
		/// 第一级字典键为模块类型。
		/// 第二级字典键为模板类型。
		/// </remarks>
		public Dictionary<string, Dictionary<string, SpecialContentTemplate>> BlockTemplates { get; set; }

		/// <summary>
		/// 内容预览数据。
		/// </summary>
		/// <remarks>
		/// 第一级字典键为模块类型。
		/// 第二级字典键为模块视图类型。
		/// 第三级字典键为预览数据对应的模板类型。
		/// </remarks>
		public Dictionary<string, Dictionary<string, Dictionary<string, string>>> ContentPreviewData { get; set; }

		/// <summary>
		/// 内容模板。
		/// </summary>
		/// <remarks>
		/// 第一级字典键为模块类型。
		/// 第二级字典键为模块视图类型。
		/// 第三级字典键为模板类型。
		/// </remarks>
		public Dictionary<string, Dictionary<string, Dictionary<string, SpecialContentTemplate>>> ContentTemplates { get; set; }
		#endregion




		/// <summary>
		/// 扩展专题模板配置对象。
		/// </summary>
		/// <param name="expansion"></param>
		public void Expand(SpecialTemplateConfiguration expansion)
		{
			if (expansion == null) return;

			if (expansion.WebsiteNavigationTemplate != null) this.WebsiteNavigationTemplate = expansion.WebsiteNavigationTemplate;
			if (expansion.MainNavigationTemplate != null) this.MainNavigationTemplate = expansion.MainNavigationTemplate;
			if (expansion.CurrentLocationTemplate != null) this.CurrentLocationTemplate = expansion.CurrentLocationTemplate;
			if (expansion.CopyrightInfoTemplate != null) this.CopyrightInfoTemplate = expansion.CopyrightInfoTemplate;
			if (expansion.TemplateCssUrls != null) this.TemplateCssUrls = expansion.TemplateCssUrls;

			if (expansion.Websites != null)
			{
				this.Websites = expansion.Websites;
			}

			if (expansion.BlockPreviewData != null)
			{
				if (this.BlockPreviewData == null) this.BlockPreviewData = expansion.BlockPreviewData;
				else
				{
					foreach (var moduleItem in expansion.BlockPreviewData)
					{
						if (!this.BlockPreviewData.ContainsKey(moduleItem.Key))
							this.BlockPreviewData.Add(moduleItem.Key, moduleItem.Value);
						else
						{
							var currentModule = this.BlockPreviewData[moduleItem.Key];
							foreach (var typeItem in moduleItem.Value)
							{
								if (!currentModule.ContainsKey(typeItem.Key))
									currentModule.Add(typeItem.Key, typeItem.Value);
								else
								{
									if (!string.IsNullOrEmpty(typeItem.Value)) currentModule[typeItem.Key] = typeItem.Value;
								}
							}
						}
					}
				}
			}

			if (expansion.ContentPreviewData != null)
			{
				if (this.ContentPreviewData == null) this.ContentPreviewData = expansion.ContentPreviewData;
				else
				{
					foreach (var moduleItem in expansion.ContentPreviewData)
					{
						if (!this.ContentPreviewData.ContainsKey(moduleItem.Key))
							this.ContentPreviewData.Add(moduleItem.Key, moduleItem.Value);
						else
						{
							var currentModule = this.ContentPreviewData[moduleItem.Key];
							foreach (var view in moduleItem.Value)
							{
								if (!currentModule.ContainsKey(view.Key))
									currentModule.Add(view.Key, view.Value);
								else
								{
									var currentView = currentModule[view.Key];
									foreach (var typeItem in view.Value)
									{
										if (!currentView.ContainsKey(typeItem.Key))
											currentView.Add(typeItem.Key, typeItem.Value);
										else
										{
											if (!string.IsNullOrEmpty(typeItem.Value)) currentView[typeItem.Key] = typeItem.Value;
										}
									}
								}
							}
						}
					}
				}
			}

			if (expansion.BlockTemplates != null)
			{
				if (this.BlockTemplates == null) this.BlockTemplates = expansion.BlockTemplates;
				else
				{
					foreach (var moduleItem in expansion.BlockTemplates)
					{
						if (!this.BlockTemplates.ContainsKey(moduleItem.Key))
							this.BlockTemplates.Add(moduleItem.Key, moduleItem.Value);
						else
						{
							var currentModule = this.BlockTemplates[moduleItem.Key];
							foreach (var typeItem in moduleItem.Value)
							{
								if (!currentModule.ContainsKey(typeItem.Key))
									currentModule.Add(typeItem.Key, typeItem.Value);
								else
								{
									if (typeItem.Value.Name != null) currentModule[typeItem.Key].Name = typeItem.Value.Name;
									if (typeItem.Value.Template != null) currentModule[typeItem.Key].Template = typeItem.Value.Template;
									if (typeItem.Value.Styles != null) currentModule[typeItem.Key].Styles = typeItem.Value.Styles;
									if (typeItem.Value.OtherParameters != null) currentModule[typeItem.Key].OtherParameters = typeItem.Value.OtherParameters;
								}
							}
						}
					}
				}
			}

			if (expansion.ContentTemplates != null)
			{
				if (this.ContentTemplates == null) this.ContentTemplates = expansion.ContentTemplates;
				else
				{
					foreach (var moduleItem in expansion.ContentTemplates)
					{
						if (!this.ContentTemplates.ContainsKey(moduleItem.Key))
							this.ContentTemplates.Add(moduleItem.Key, moduleItem.Value);
						else
						{
							var currentModule = this.ContentTemplates[moduleItem.Key];
							foreach (var view in moduleItem.Value)
							{
								if (!currentModule.ContainsKey(view.Key))
									currentModule.Add(view.Key, view.Value);
								else
								{
									var currentView = currentModule[view.Key];
									foreach (var typeItem in view.Value)
									{
										if (!currentView.ContainsKey(typeItem.Key))
											currentView.Add(typeItem.Key, typeItem.Value);
										else
										{
											if (typeItem.Value.Name != null) currentView[typeItem.Key].Name = typeItem.Value.Name;
											if (typeItem.Value.Template != null) currentView[typeItem.Key].Template = typeItem.Value.Template;
											if (typeItem.Value.Styles != null) currentView[typeItem.Key].Styles = typeItem.Value.Styles;
											if (typeItem.Value.OtherParameters != null) currentView[typeItem.Key].OtherParameters = typeItem.Value.OtherParameters;
										}
									}
								}
							}
						}
					}
				}
			}
		}




		/// <summary>
		/// 获取区块预览数据。
		/// </summary>
		/// <param name="moduleType">模块类型。</param>
		/// <param name="viewType">视图类型。</param>
		/// <returns>区块预览数据。</returns>
		public string GetBlockPreviewData(string moduleType, string viewType)
		{
			var datas = this.BlockPreviewData;

			if (string.IsNullOrEmpty(moduleType) || datas == null) return null;
			if (!datas.ContainsKey(moduleType)) return null;
			var datas2 = datas[moduleType];

			if (!string.IsNullOrEmpty(viewType) && datas2.ContainsKey(viewType))
				return datas2[viewType];
			foreach (var val in datas2)
				return val.Value;
			return null;
		}

		/// <summary>
		/// 获取内容预览数据。
		/// </summary>
		/// <param name="moduleType">模块类型。</param>
		/// <param name="moduleView">模块视图</param>
		/// <param name="viewType">视图类型。</param>
		/// <returns>内容预览数据。</returns>
		public string GetContentPreviewData(string moduleType, string moduleView, string viewType)
		{
			var datas = this.ContentPreviewData;

			if (string.IsNullOrEmpty(moduleType) || string.IsNullOrEmpty(moduleView) || datas == null) return null;
			if (!datas.ContainsKey(moduleType)) return null;
			var datas2 = datas[moduleType];

			if (!datas2.ContainsKey(moduleView)) return null;
			var datas3 = datas2[moduleView];

			if (!string.IsNullOrEmpty(viewType) && datas3.ContainsKey(viewType))
				return datas3[viewType];
			foreach (var val in datas3)
				return val.Value;
			return null;
		}

		/// <summary>
		/// 获取区块模板名称。
		/// </summary>
		/// <param name="moduleType">模块类别。</param>
		/// <returns>区块模板名称。</returns>
		public Dictionary<string, string> GetBlockTemplateNames(string moduleType)
		{
			var templates = this.BlockTemplates;

			if (string.IsNullOrEmpty(moduleType) || templates == null) return null;
			if (!templates.ContainsKey(moduleType)) return null;
			var ts = templates[moduleType];

			if (ts == null) return null;
			var q = from p in ts select new { Key = p.Key, Value = (p.Value == null || string.IsNullOrEmpty(p.Value.Name)) ? p.Key : p.Value.Name };
			Dictionary<string, string> names = new Dictionary<string, string>();
			foreach (var i in q)
				names.Add(i.Key, i.Value);
			return names;
		}

		/// <summary>
		/// 获取内容模板名称。
		/// </summary>
		/// <param name="moduleType">模块类别。</param>
		/// <param name="moduleView">模块视图。</param>
		/// <returns>内容模板名称。</returns>
		public Dictionary<string, string> GetContentTemplateNames(string moduleType, string moduleView)
		{
			var templates = this.ContentTemplates;

			if (string.IsNullOrEmpty(moduleType) || string.IsNullOrEmpty(moduleView) || templates == null) return null;
			if (!templates.ContainsKey(moduleType)) return null;
			var templates2 = templates[moduleType];

			if (!templates2.ContainsKey(moduleView)) return null;
			var ts = templates2[moduleView];

			if (ts == null) return null;
			var q = from p in ts select new { Key = p.Key, Value = (p.Value == null || string.IsNullOrEmpty(p.Value.Name)) ? p.Key : p.Value.Name };
			Dictionary<string, string> names = new Dictionary<string, string>();
			foreach (var i in q)
				names.Add(i.Key, i.Value);
			return names;
		}

		/// <summary>
		/// 获取区块模板。
		/// </summary>
		/// <param name="moduleType">模块类别。</param>
		/// <param name="listType">列表类型。</param>
		/// <returns>区块模板。</returns>
		public SpecialContentTemplate GetBlockTemplate(string moduleType, string listType)
		{
			var templates = this.BlockTemplates;

			if (string.IsNullOrEmpty(moduleType) || templates == null) return null;
			if (!templates.ContainsKey(moduleType)) return null;
			var templates2 = templates[moduleType];

			if (templates2 == null) return null;
			if (!string.IsNullOrEmpty(listType) && templates2.ContainsKey(listType))
				return templates2[listType];
			foreach (var val in templates2)
				return val.Value;
			return null;
		}

		/// <summary>
		/// 获取内容模板。
		/// </summary>
		/// <param name="moduleType">模块类别。</param>
		/// <param name="moduleView">模块视图。</param>
		/// <param name="listType">列表类型。</param>
		/// <returns>内容模板。</returns>
		public SpecialContentTemplate GetContentTemplate(string moduleType, string moduleView, string listType)
		{
			var templates = this.ContentTemplates;

			if (string.IsNullOrEmpty(moduleType) || string.IsNullOrEmpty(moduleView) || templates == null) return null;
			if (!templates.ContainsKey(moduleType)) return null;
			var templates2 = templates[moduleType];

			if (!templates2.ContainsKey(moduleView)) return null;
			var templates3 = templates2[moduleView];

			if (templates3 == null) return null;
			if (!string.IsNullOrEmpty(listType) && templates3.ContainsKey(listType))
				return templates3[listType];
			foreach (var val in templates3)
				return val.Value;
			return null;
		}





		/// <summary>
		/// 获取配置Url。
		/// </summary>
		/// <param name="templateFolder">模板文件夹名称。</param>
		/// <param name="culture">地区语言。</param>
		/// <returns>配置的Url。</returns>
		private static string GetConfigurationUrl(string templateFolder, string culture)
		{
			return SpecialPages.TemplateRootUrl + (string.IsNullOrEmpty(templateFolder) ? "" : templateFolder + "/") + "Configuration" + (string.IsNullOrEmpty(culture) ? "" : "." + culture) + ".js";
		}

		/// <summary>
		/// 获取配置路径。
		/// </summary>
		/// <param name="templateFolder">模板文件夹名称。</param>
		/// <param name="culture">地区语言。</param>
		/// <returns>配置的路径。</returns>
		private static string GetConfigurationPath(string templateFolder, string culture)
		{
			return System.Web.HttpContext.Current.Server.MapPath(GetConfigurationUrl(templateFolder, culture));
		}

		/// <summary>
		/// 获取配置Json字符串。
		/// </summary>
		/// <param name="templateFolder">模板文件夹名称。</param>
		/// <param name="culture">地区语言。</param>
		/// <returns>配置的Json字符串。</returns>
		private static string GetConfigurationJson(string templateFolder, string culture)
		{
			string path = GetConfigurationPath(templateFolder, culture);

			if (!File.Exists(path))
				return null;
			return File.ReadAllText(path);
		}

		/// <summary>
		/// 加载模板配置。
		/// </summary>
		/// <param name="culture">地区语言。</param>
		/// <returns>模板配置。</returns>
		public static SpecialTemplateConfiguration Load(string culture)
		{
			return Load(null, culture);
		}

		/// <summary>
		/// 加载模板配置。
		/// </summary>
		/// <param name="templateFolder">模板文件夹名称。</param>
		/// <param name="culture">地区语言。</param>
		/// <returns>模板配置。</returns>
		public static SpecialTemplateConfiguration Load(string templateFolder, string culture)
		{
			string json = GetConfigurationJson(templateFolder, culture);
			if (string.IsNullOrEmpty(json)) return null;

			return Serialization.DeserializeJson<SpecialTemplateConfiguration>(json);
		}

		/// <summary>
		/// 加载已经从基础配置扩展的配置。
		/// </summary>
		/// <param name="templateFolder">模板的文件夹名称。</param>
		/// <param name="culture">地区语言。</param>
		/// <returns>从基础配置扩展的配置。</returns>
		public static SpecialTemplateConfiguration LoadExpansion(string templateFolder, string culture)
		{
			return GetCacheTemplateConfiguration(templateFolder, culture);
		}



		#region 缓存项
		private static Cache _cache;

		private static Cache Cache
		{
			get
			{
				if (_cache != null) return _cache;
				_cache = HttpContext.Current == null ? null : HttpContext.Current.Cache;
				return _cache;
			}
		}

		private static string BuildCacheKey(string templateFolder, string culture)
		{
			return "SpecialTemplateConfiguration_" + templateFolder + (string.IsNullOrEmpty(culture) ? "" : "\\" + culture);
		}

		/// <summary>
		/// 扩展模板配置。
		/// </summary>
		/// <param name="con">原配置。</param>
		/// <param name="configFiles">配置文件集合。用于缓存依赖。</param>
		/// <param name="templateFolder">模板文件夹。</param>
		/// <param name="culture">地区语言。</param>
		/// <returns>扩展后的模板配置。</returns>
		private static SpecialTemplateConfiguration ExpandTemplateConfiguration(SpecialTemplateConfiguration con, List<string> configFiles, string templateFolder, string culture)
		{
			configFiles.Add(GetConfigurationPath(templateFolder, culture));
			string json = GetConfigurationJson(templateFolder, culture);
			if (!string.IsNullOrEmpty(json))
			{
				SpecialTemplateConfiguration con2 = Serialization.DeserializeJson<SpecialTemplateConfiguration>(json);
				if (con2 != null)
				{
					if (con != null)
						con.Expand(con2);
					else
						con = con2;
				}
			}

			return con;
		}

		/// <summary>
		/// 获取缓存模板配置。
		/// </summary>
		/// <param name="templateFolder">模板文件夹。</param>
		/// <param name="culture">地区语言。</param>
		/// <returns>模板配置。</returns>
		private static SpecialTemplateConfiguration GetCacheTemplateConfiguration(string templateFolder, string culture)
		{
			Cache cache = Cache;
			string key = BuildCacheKey(templateFolder, culture);

			SpecialTemplateConfiguration con = null;
			if (cache != null)
			{
				con = cache[key] as SpecialTemplateConfiguration;
				if (con != null) return con;
			}

			// 配置依赖文件
			List<string> configFiles = new List<string>();

			// 添加非区域性的主配置文件
			con = ExpandTemplateConfiguration(con, configFiles, null, null);

			// 添加区域性的主配置文件
			if (!string.IsNullOrEmpty(culture))
				con = ExpandTemplateConfiguration(con, configFiles, null, culture);

			// 添加子配置文件
			if(!string.IsNullOrEmpty(templateFolder))
			{
				// 添加非区域性的子配置文件
				con = ExpandTemplateConfiguration(con, configFiles, templateFolder, null);

				// 添加区域性的子配置文件
				if (!string.IsNullOrEmpty(culture))
					con = ExpandTemplateConfiguration(con, configFiles, templateFolder, culture);
			}

			if (cache != null)
			{
				cache.Insert(key, con, new CacheDependency(configFiles.ToArray()));
			}
			return con;
		}
		#endregion
	}
}